/*=====================================================================================================================
                    Copyright(c) 2009 Geometric PLM Software Corp. All rights reserved.
                             Unpublished - All rights reserved
=======================================================================================================================
File description:
    Filename: vector_c.h
    Module  : Common module.

        This file includes the operations of the simluative vector.

=======================================================================================================================
Date               Name              Description of Change
26-Jan-2010        Jerry,Wu          Initialize creation
$HISTORY$
=====================================================================================================================*/
#ifndef _cplusplus
#define _CRT_SECURE_NO_DEPRECATE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <base_utils\mem.h>
#include <memory.h>
#include "list_c.h"



List_Node_t* LIST_createListHead(void *data)
{
    List_Node_t *newNode = NULL;
    newNode = MEM_alloc(sizeof(List_Node_t));
    newNode->preNode = NULL;
    newNode->data = data;
    newNode->nextNode = NULL;
    return newNode;
}

void LIST_assign(List_Node_t *curNode, void *data)
{
    if(curNode != NULL)
    {
        curNode->data = data;
    }
}

void* LIST_get_data(List_Node_t *curNode)
{
    void *retValue = NULL;
    if(curNode != NULL)
    {
        retValue = curNode->data;
    }
    return retValue;
}

List_Node_t* LIST_getPreNode(List_Node_t *curNode)
{
    List_Node_t *preNode = NULL;
    if(curNode != NULL)
    {
        preNode = curNode->preNode;
    }
    return preNode;
}

List_Node_t* LIST_getNextNode(List_Node_t *curNode)
{
    List_Node_t *nextNode = NULL;
    if(curNode != NULL)
    {
        nextNode = curNode->nextNode;
    }
    return nextNode;
}

List_Node_t* LIST_back(List_Node_t *curNode)
{
    List_Node_t *endNode = NULL;
    if(curNode != NULL)
    {
        while(curNode->nextNode != NULL)
        {
            curNode = LIST_getNextNode(curNode);
        }
        endNode = curNode;
    }
    return endNode;
}

List_Node_t*  LIST_begin(List_Node_t *curNode)
{
    List_Node_t *beginNode = NULL;
    if(curNode != NULL)
    {
        while(curNode->preNode != NULL)
        {
            curNode = LIST_getPreNode(curNode);
        }
        beginNode = curNode;
    }
    return beginNode;
}

void LIST_clear(List_Node_t **curNode, FREE_FUNC freeFunc)
{
    if(*curNode != NULL)
    {
        List_Node_t *posNode = NULL;
        for(posNode = LIST_begin(*curNode); posNode != NULL; posNode = LIST_getNextNode(posNode))
        {
            if(posNode->preNode!= NULL) 
            {
                if(posNode->preNode->data != NULL)
                {
                    freeFunc(posNode->preNode->data);
                }
                MEM_free(posNode->preNode);
            }
            if(posNode->nextNode == NULL)
            {
                if(posNode->data != NULL)
                {
                    freeFunc(posNode->data);
                }
                MEM_free(posNode);
                posNode = NULL;
            }
        }
        *curNode = NULL;
    }
}

int LIST_size(List_Node_t *curNode)
{
    int size = 0;
    if(curNode != NULL)
    {
        List_Node_t *posNode = NULL;
        posNode = LIST_begin(curNode);
        while(posNode->nextNode != NULL)
        {
            posNode = posNode->nextNode;
            size++;
        }
        size++;
    }
    return size;
}

List_Node_t* LIST_pop_back(List_Node_t **curNode, FREE_FUNC freeFunc)
{
    List_Node_t* retNode = NULL; 
    if(*curNode != NULL)
    {
        List_Node_t *backNode = NULL, *preNode = NULL;
        backNode = LIST_back(*curNode);
        preNode = backNode->preNode;
        (*freeFunc)(backNode->data);
        MEM_free(backNode);
        if(backNode == *curNode)
        {
            curNode = NULL;
        }
        backNode = NULL;
        if(preNode != NULL)
        {
            preNode->nextNode = NULL;
            retNode = preNode;
        }
    }
    return retNode;
}

List_Node_t* LIST_pop_front(List_Node_t **curNode, FREE_FUNC freeFunc)
{
    List_Node_t* retNode = NULL; 
    if(curNode != NULL)
    {
        List_Node_t *beginNode = NULL, *nextNode = NULL;
        beginNode = LIST_begin(*curNode);
        nextNode = beginNode->nextNode;
        (*freeFunc)(beginNode->data);
        MEM_free(beginNode);
        if(beginNode == *curNode)
        {
            curNode = NULL;
        }
        beginNode = NULL;
        if(nextNode != NULL)
        {
            nextNode->preNode = NULL;
            retNode = nextNode;
        }
    }
    return retNode;
}

List_Node_t* LIST_push_back(List_Node_t *curNode, void *data)
{
    List_Node_t* newNode = NULL;
    if(curNode == NULL)
    {
        newNode = LIST_createListHead(data);
    }
    else
    {
        List_Node_t *backNode = NULL;
        backNode = LIST_back(curNode);
        newNode = MEM_alloc(sizeof(List_Node_t));

        newNode->preNode = backNode;
        newNode->data = data;
        newNode->nextNode = NULL;

        backNode->nextNode = newNode;
    }
    return newNode;
}

List_Node_t* LIST_push_front(List_Node_t *curNode, void *data)
{
    List_Node_t* newNode = NULL;
    if(curNode == NULL)
    {
        newNode = LIST_createListHead(data);
    }
    else
    {
        List_Node_t *beginNode = NULL;
        beginNode = LIST_begin(curNode);
        newNode = MEM_alloc(sizeof(List_Node_t));

        newNode->preNode = NULL;
        newNode->data = data;;
        newNode->nextNode = beginNode;

        beginNode->preNode = newNode;
    }
    return newNode;
}

List_Node_t* LIST_remove(List_Node_t **curNode, FREE_FUNC freeFunc)
{
    List_Node_t* retNode = NULL;
    if(*curNode != NULL)
    {
        List_Node_t *preNode = NULL, *nextNode = NULL;
        preNode = (*curNode)->preNode;
        nextNode = (*curNode)->nextNode;

        (*freeFunc)((*curNode)->data);
        MEM_free((*curNode));
        (*curNode) = NULL;
        if(preNode != NULL)
        {
            preNode->nextNode = nextNode;
            retNode = preNode;
        }
        if(nextNode != NULL)
        {
            nextNode->preNode = preNode;
            retNode = nextNode;
        }
    }
    return retNode;
}

List_Node_t* LIST_insert(List_Node_t *curNode, void *data)
{
    List_Node_t *newNode = NULL;
    if(curNode == NULL)
    {
        newNode = LIST_createListHead(data);
    }
    else
    {
        List_Node_t *nextNode = NULL;
        nextNode = curNode->nextNode;
        
        newNode = MEM_alloc(sizeof(List_Node_t));

        newNode->preNode = curNode;
        newNode->data = data;
        newNode->nextNode = nextNode;

        curNode->nextNode = newNode;
        if(nextNode != NULL)
        {
            nextNode->preNode = newNode;
        }
    }
    return newNode;
}
